#include "GlslOld.h"


GlslOld::GlslOld (char *vert, char *geom, char *frag)
{
   vPath = vert;
   gPath = geom;
   fPath = frag;
}

void GlslOld::setShaders ()
{

   GLuint v, g, f;
   char *vs, *gs, *fs;

   // Create shader handlers
   v = glCreateShader (GL_VERTEX_SHADER);
   f = glCreateShader (GL_FRAGMENT_SHADER);

   // Read source code from files
   vs = textFileRead (vPath);
   fs = textFileRead (fPath);

   const char * vv = vs;
   const char * ff = fs;

   // Set shader source
   glShaderSource (v, 1, &vv, NULL);
   glShaderSource (f, 1, &ff, NULL);

   free (vs);  free (fs);

   // Compile all shaders
   glCompileShader (v);
   glCompileShader (f);

   if (gPath != NULL) {
      g = glCreateShader (GL_GEOMETRY_SHADER);
      const char * gg = gs;
      gs = textFileRead (gPath);
      glShaderSource (g, 1, &gg, NULL);
      glCompileShader (g);
      free (gs);
   }
   // Create the program
   p = glCreateProgram ();

   // Attach shaders to program
   glAttachShader (p, v);
   if (gPath != NULL) glAttachShader (p, g);
   glAttachShader (p, f);

   // Link and set program to use
   glLinkProgram (p);

   printShaderInfoLog (v);
   printShaderInfoLog (f);
   printProgramInfoLog (p);

   printf ("\nProgram id: %d\n", p);
   printOglError (__FILE__, __LINE__);
}

void GlslOld::printShaderInfoLog (GLuint obj)
{
   int infologLength = 0;
   int charsWritten = 0;
   char *infoLog;

   glGetShaderiv (obj, GL_INFO_LOG_LENGTH, &infologLength);

   if (infologLength > 0) {
      infoLog = (char *)malloc (infologLength);
      glGetShaderInfoLog (obj, infologLength, &charsWritten, infoLog);
      printf ("%s\n", infoLog);
      free (infoLog);
   }
}

void GlslOld::printProgramInfoLog (GLuint obj)
{
   int infologLength = 0;
   int charsWritten = 0;
   char *infoLog;

   glGetProgramiv (obj, GL_INFO_LOG_LENGTH, &infologLength);

   if (infologLength > 0) {
      infoLog = (char *)malloc (infologLength);
      glGetProgramInfoLog (obj, infologLength, &charsWritten, infoLog);
      printf ("%s\n", infoLog);
      free (infoLog);
   }
}

char *GlslOld::textFileRead (char *fn)
{

   FILE *fp;
   char *content = NULL;

   int count = 0;

   if (fn != NULL) {
      fp = fopen (fn, "rt");

      if (fp != NULL) {

         fseek (fp, 0, SEEK_END);
         count = ftell (fp);
         rewind (fp);

         if (count > 0) {
            content = (char *)malloc (sizeof(char)* (count + 1));
            count = fread (content, sizeof(char), count, fp);
            content[count] = '\0';
         }
         fclose (fp);
      }
   }
   return content;
}

//only One active each time
void GlslOld::setActive (bool active)
{
   if (active)
      glUseProgram (p);
   else
      glUseProgram (0); //disable actual program
}

GLint GlslOld::getUniformLoc (char *name)
{
   return glGetUniformLocation (p, name);
}

GLint GlslOld::getAttribLoc (char *name)
{
   return glGetAttribLocation (p, name);
}

int GlslOld::printOglError (char *file, int line)
{
   //
   // Returns 1 if an OpenGL error occurred, 0 otherwise.
   //
   GLenum glErr;
   int    retCode = 0;

   glErr = glGetError ();
   while (glErr != GL_NO_ERROR) {
      printf ("glError in file %s @ line %d: %s\n", file, line, gluErrorString (glErr));
      retCode = 1;
      glErr = glGetError ();
   }
   return retCode;
}

GlslOld::~GlslOld ()
{
}
